package com.young.commom.httpclient.components;

import com.young.commom.httpclient.AbstractHttpClientTemplate;
import com.young.commom.httpclient.HttpClientConfiguration;
import com.young.commom.httpclient.HttpResult;
import com.young.common.core.util.Utils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @description：
 * @author: yangyahui01
 * @date: 11/29/24 1:10 PM
 */
public class HttpComponentsClientTemplate extends AbstractHttpClientTemplate {
    private CloseableHttpClient httpClient;
    private volatile boolean init = false;
    private List<HttpRequestInterceptor> requestInterceptors;
    private List<HttpResponseInterceptor> responseInterceptors;

    public void setRequestInterceptors(List<HttpRequestInterceptor> requestInterceptors) {
        this.requestInterceptors = requestInterceptors;
    }

    public void setResponseInterceptors(List<HttpResponseInterceptor> responseInterceptors) {
        this.responseInterceptors = responseInterceptors;
    }

    public HttpComponentsClientTemplate() {
    }

    public HttpComponentsClientTemplate(HttpClientConfiguration configuration) {
        super(configuration);
    }

    public synchronized void init() {
        if (!this.init) {
            super.init();
            if (this.requestInterceptors == null) {
                this.requestInterceptors = new ArrayList();
            }

            HttpComponentsHttpRequestInterceptor interceptor = new HttpComponentsHttpRequestInterceptor();
            if (this.configuration.isDnsResolverEnabled()) {
                interceptor.setDnsResolver(this.configuration.getNamingResolver());
            }

            interceptor.setGlobalHeaders(this.configuration.getGlobalHeaders());
            this.requestInterceptors.add(interceptor);
            this.httpClient = HttpComponentsClientBuilder.build(this.getConfiguration(), this.requestInterceptors, this.responseInterceptors);
            this.init = true;
        }
    }

    private void headers(RequestBuilder requestBuilder, Map<String, String> headers) {
        if (headers != null && !headers.isEmpty()) {
            Iterator var3 = headers.entrySet().iterator();

            while(var3.hasNext()) {
                Map.Entry<String, String> entry = (Map.Entry)var3.next();
                String value = entry.getValue() == null ? "" : (String)entry.getValue();
                requestBuilder.addHeader((String)entry.getKey(), value);
            }

        }
    }

    public HttpResult get(String uri) {
        return this.get(uri, (Map)null);
    }

    public HttpResult get(String uri, Map<String, String> parameters) {
        return this.get(uri, parameters, (Map)null);
    }

    public HttpResult get(String uri, Map<String, String> parameters, Map<String, String> headers) {
        if (StringUtils.isBlank(uri)) {
            return null;
        } else {
            try {
                RequestBuilder requestBuilder = RequestBuilder.get(Utils.url(uri, parameters, this.charset));
                requestBuilder.setCharset(Charset.forName(this.charset));
                String contentType = MessageFormat.format("application/json; charset={0}", this.charset);
                requestBuilder.addHeader("Content-Type", contentType);
                this.headers(requestBuilder, headers);
                HttpUriRequest request = requestBuilder.build();
                return this.process(request);
            } catch (Exception var7) {
                throw new RuntimeException(var7);
            }
        }
    }

    public HttpResult post(String uri) {
        if (StringUtils.isBlank(uri)) {
            return null;
        } else {
            try {
                RequestBuilder requestBuilder = RequestBuilder.post(uri);
                requestBuilder.setCharset(Charset.forName(this.charset));
                String contentType = MessageFormat.format("application/json; charset={0}", this.charset);
                requestBuilder.addHeader("Content-Type", contentType);
                HttpUriRequest request = requestBuilder.build();
                return this.process(request);
            } catch (Exception var5) {
                throw new RuntimeException(var5);
            }
        }
    }

    public HttpResult post(String uri, String content) {
        return this.postBody(uri, content, (Map)null, (Map)null);
    }

    public HttpResult post(String uri, String content, Map<String, String> parameters) {
        return this.postBody(uri, content, parameters, (Map)null);
    }

    public HttpResult post(String uri, String content, Map<String, String> parameters, Map<String, String> headers) {
        return this.postBody(uri, content, parameters, headers);
    }

    private HttpResult postBody(String uri, String content, Map<String, String> parameters, Map<String, String> headers) {
        if (StringUtils.isBlank(uri)) {
            return null;
        } else {
            try {
                RequestBuilder requestBuilder = RequestBuilder.post(Utils.url(uri, parameters, this.charset));
                requestBuilder.setCharset(Charset.forName(this.charset));
                StringEntity entity = new StringEntity(content == null ? "" : content, ContentType.create("application/json", this.charset));
                requestBuilder.setEntity(entity);
                this.headers(requestBuilder, headers);
                HttpUriRequest request = requestBuilder.build();
                return this.process(request);
            } catch (Exception var8) {
                throw new RuntimeException(var8);
            }
        }
    }

    public HttpResult post(String uri, Map<String, String> parameters) {
        return this.postForm(uri, parameters, (Map)null);
    }

    public HttpResult post(String uri, Map<String, String> parameters, Map<String, String> headers) {
        return this.postForm(uri, parameters, headers);
    }

    private HttpResult postForm(String uri, Map<String, String> parameters, Map<String, String> headers) {
        if (StringUtils.isBlank(uri)) {
            return null;
        } else {
            try {
                RequestBuilder requestBuilder = RequestBuilder.post(uri);
                requestBuilder.setCharset(Charset.forName(this.charset));
                if (parameters != null) {
                    String contentType = MessageFormat.format("application/x-www-form-urlencoded; charset={0}", this.charset);
                    requestBuilder.addHeader("Content-Type", contentType);
                    Iterator var6 = parameters.entrySet().iterator();

                    while(var6.hasNext()) {
                        Map.Entry<String, String> entry = (Map.Entry)var6.next();
                        String value = entry.getValue() == null ? "" : (String)entry.getValue();
                        requestBuilder.addParameter((String)entry.getKey(), value);
                    }
                }

                this.headers(requestBuilder, headers);
                HttpUriRequest request = requestBuilder.build();
                return this.process(request);
            } catch (Exception var9) {
                throw new RuntimeException(var9);
            }
        }
    }

    private HttpResult process(HttpUriRequest request) throws Exception {
        HttpResult result = new HttpResult();
        CloseableHttpResponse response = this.httpClient.execute(request);
        Throwable var4 = null;

        HttpResult var8;
        try {
            StatusLine statusLine = response.getStatusLine();
            int statusCode = statusLine.getStatusCode();
            result.setCode(statusCode);
            if (statusCode != 200) {
                request.abort();
                HttpResult var20 = result;
                return var20;
            }

            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result.setContent(EntityUtils.toString(entity, this.charset));
            }

            EntityUtils.consume(entity);
            var8 = result;
        } catch (Throwable var18) {
            var4 = var18;
            throw var18;
        } finally {
            if (response != null) {
                if (var4 != null) {
                    try {
                        response.close();
                    } catch (Throwable var17) {
                        var4.addSuppressed(var17);
                    }
                } else {
                    response.close();
                }
            }

        }

        return var8;
    }

    public void close() throws IOException {
        if (this.httpClient != null) {
            this.httpClient.close();
        }

    }

    public HttpClient getClient() {
        return this.httpClient;
    }

    public String clientType() {
        return "httpComponents";
    }
}
